package com.gcloud.mesh.dcs.chain.k8s;

import com.alibaba.fastjson.JSONObject;
import com.gcloud.mesh.asset.dao.CloudResourceConfigDao;
import com.gcloud.mesh.asset.entity.CloudResourceConfigEntity;
import com.gcloud.mesh.dcs.chain.FilterChain;
import com.gcloud.mesh.dcs.chain.IMigrationStepChain;
import com.gcloud.mesh.dcs.dao.AppInstanceDao;
import com.gcloud.mesh.dcs.dao.SchedulerStepDao;
import com.gcloud.mesh.dcs.entity.AppInstanceEntity;
import com.gcloud.mesh.dcs.entity.SchedulerStepEntity;
import com.gcloud.mesh.dcs.enums.RestveleroBackupStatus;
import com.gcloud.mesh.header.exception.BaseException;
import com.gcloud.mesh.header.exception.SchedulerErrorCode;
import com.gcloud.mesh.header.msg.restvelero.CreateVeleroBackupMsg;
import com.gcloud.mesh.header.vo.restvelero.RestveleroBackupDetailVo;
import com.gcloud.mesh.header.vo.restvelero.RestveleroBackupReply;
import com.gcloud.mesh.sdk.RestveleroSDK;
import com.gcloud.mesh.supplier.enums.K8sClusterType;
import com.gcloud.mesh.supplier.enums.SystemType;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.exception.MyBusinessException;
import org.jeecg.common.exception.ParamException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
@Slf4j
public class BackupNamespace implements IMigrationStepChain{

    @Autowired
    private RestveleroSDK restveleroSDK;

    @Autowired
    private SchedulerStepDao schedulerStepDao;

    @Autowired
    private CloudResourceConfigDao cloudResourceConfigDao;

    @Autowired
    private AppInstanceDao appInstanceDao;



    @Override
    public void doExec(String schedulerJobId, String attach, FilterChain filterChain, IMigrationStepChain stepChain) {
        try {

            JSONObject jsonObject = JSONObject.parseObject(attach);

            String jobId = jsonObject.getString("id");
            String instanceId = jsonObject.getString("instanceId");
            String srcCloudResourceId = jsonObject.getString("cloudResourceId");
            String dstCloudResourceId = jsonObject.getString("dstCloudResourceId");

            CloudResourceConfigEntity srcCloudResource = cloudResourceConfigDao.findOneByProperty("cloudResourceId", srcCloudResourceId);
            CloudResourceConfigEntity dstCloudResource = cloudResourceConfigDao.findOneByProperty("cloudResourceId", dstCloudResourceId);
            if(srcCloudResource==null) throw new MyBusinessException("原资源ID错误");
            if(dstCloudResource==null) throw new MyBusinessException("目标资源ID错误");
            JSONObject srcCloudJson = JSONObject.parseObject(srcCloudResource.getConfig());
            JSONObject dstCloudJson = JSONObject.parseObject(dstCloudResource.getConfig());
            String srcUrl = srcCloudJson.getString(K8sClusterType.RESTVELERO_IP.getName());
            String destUrl = dstCloudJson.getString(K8sClusterType.RESTVELERO_IP.getName());

            log.debug("[schedule] 数据中心调度开始,id:{}, appId:{}", jobId, instanceId);
            AppInstanceEntity appInstanceEntity = appInstanceDao.findOneByProperty("instanceId",instanceId);
            if (appInstanceEntity == null)throw new ParamException(SchedulerErrorCode.APP_NOT_EXIST);
            String backupName = appInstanceEntity.getName() + "-" + UUID.randomUUID().toString() + "-" + instanceId;
            String namespace = appInstanceEntity.getName();

            RestveleroBackupReply resBackup = restveleroSDK.backup(srcUrl, backupName, new CreateVeleroBackupMsg(namespace));
            if (resBackup.getStatus() != 200) {
                throw new BaseException(SchedulerErrorCode.RESTORE_OPERATE_FAILED);
            }
            jsonObject.put("srcUrl",srcUrl);
            jsonObject.put("dstUrl",destUrl);
            jsonObject.put("backupName",backupName);
            jsonObject.put("appInstanctName",appInstanceEntity.getName());

            schedulerStepDao.updateAttachBySchedulerJobId(schedulerJobId,jsonObject.toString());

            filterChain.doExec(schedulerJobId,jsonObject.toString(),filterChain,stepChain);

        }catch (ParamException e){
            log.error("ParamException",e);
            throw new MyBusinessException(e.getErrorMsg());
        }catch (Exception e){
            log.error("Exception",e);
            throw new MyBusinessException("备份操作失败，请联系管理员");
        }
    }

    @Override
    public String chainType() {
        return SystemType.K8S.getName();
    }

    @Override
    public String chainName(String attach) {
        JSONObject jsonObject = JSONObject.parseObject(attach);
        return String.format("%s执行镜像备份",jsonObject.getString("srcDatacenterName"));
    }

    @Override
    public int getOrder() {
        return 1;
    }

    @Override
    public boolean checkStatus(String stepId) {
        String uid = UUID.randomUUID().toString();
        try {
            SchedulerStepEntity stepEntity = schedulerStepDao.getById(stepId);
            if(stepEntity!=null){
                JSONObject jsonObject = JSONObject.parseObject(stepEntity.getAttach());
                String destUrl = jsonObject.getString("dstUrl");
                String backupName = jsonObject.getString("backupName");
                RestveleroBackupDetailVo backup = restveleroSDK.backupDetail(destUrl, backupName);
                log.info("[schedule] 数据中心调度-备份状态,uid:{},id:{}, status:{}",uid, backupName, backup.getData().getStatus().getPhase());
                if (backup != null && HttpStatus.OK.value() == backup.getStatus() && RestveleroBackupStatus.COMPLETED.getValue().equals(backup.getData().getStatus().getPhase())) {
                    return true;
                }
            }
        }catch(Exception e){
            log.error("========>"+uid+"检查备份镜像状态失败",e);
        }
        return false;
    }

    @Override
    public boolean isSyncChain() {
        return false;
    }

    @Override
    public String getExecResult() {
        return null;
    }
}
